﻿using System;
using UnityEditorInternal;
using UnityEngine;
using UnityEditor;
using TileMapEditor.Internal;

namespace TileMapEditor.Core
{
	public class TileMapUtilityWindow : EditorWindow
	{
	    protected static Styles _styles;
	
	
	    protected const float _border_margin = 10f;
	    protected const float _scrollbar_margin = 16f;
	
	    protected const float _inspector_window_margin = 8f;
	    protected const float _inspector_width = 330f;
	    protected const float _inspector_height = 500f;
	
	    protected const float _min_zoom_percentage = 0.9f;
	    protected const float _max_zoom = 50f;
	
	    protected const float _wheel_zoom_speed = 0.03f;
	    protected const float _mouse_zoom_speed = 0.005f;
	
	    protected Texture2D _texture;
	    protected Texture2D _texture_alpha_override;
	
	    /// <summary>
	    /// The size (x-max, y-max)
	    /// </summary>
	    protected static Vector2 _size;
	
	    protected Rect _texture_view_rect = new Rect( 0, 0, 200, 200 );
	    protected Rect _texture_rect;
	
	    protected bool _show_alpha = false;
	    protected float _zoom = -1f;
	    protected float _mip_level = 0f;
	
	    protected Vector2 _scroll_position = default( Vector2 );
	
	    /// <summary>
	    /// The mouse position relative to the corner of left bottom of the texture.
	    /// </summary>
	    protected Vector2 _mouse_position;
	
	    /// <summary>
	    /// Slot position relative to the grid coordinate
	    /// </summary>
	    protected Vector2 _slot_position;
	
	    protected bool _wants_mouse_move = true;
	
	    protected Rect maxScrollRect
	    {
	        get
	        {
	            float num = (float) _texture.width * 0.5f * _zoom;
	            float num2 = (float) _texture.height * 0.5f * _zoom;
	
	            return new Rect( -num, -num2, _texture_view_rect.width + num * 2f, _texture_view_rect.height + num2 * 2f );
	        }
	    }
	
	    protected Rect maxRect
	    {
	        get
	        {
	            float num = _texture_view_rect.width * 0.5f / GetMinZoom();
	            float num2 = _texture_view_rect.height * 0.5f / GetMinZoom();
	            float x = -num;
	            float y = -num2;
	
	            float width = (float) _texture.width + num * 2f;
	            float height = (float) _texture.height + num2 * 2f;
	
	            return new Rect( x, y, width, height );
	        }
	    }
	
	    protected void InitStyles()
	    {
	        if ( null == _styles )
	            _styles = new Styles();
	    }
	
	    protected float GetMinZoom()
	    {
	        float result;
	        if ( _texture == null )
	        {
	            return 1f;
	        }
	        else
	        {
	            result = Mathf.Min( new float[] {
	                    _texture_view_rect.width / (float) _texture.width,
	                    _texture_view_rect.height / (float) _texture.height,
	                    50f
	                } ) * .9f;
	        }
	
	        return result;
	    }
	
	    protected void HandleZoom()
	    {
	        bool flag = Event.current.alt && Event.current.button == 1;
	        if ( flag )
	        {
	            EditorGUIUtility.AddCursorRect( _texture_view_rect, MouseCursor.Zoom ); // change mouse
	        }
	
	        if ( ( ( Event.current.type == EventType.MouseUp || Event.current.type == EventType.MouseDown ) && flag )
	            || ( ( Event.current.type == EventType.KeyUp || Event.current.type == EventType.KeyDown )
	            && Event.current.keyCode == KeyCode.LeftAlt ) )
	        {
	            base.Repaint();
	        }
	
	        // handling zooming
	        if ( Event.current.type == EventType.ScrollWheel
	            || ( Event.current.type == EventType.MouseDrag
	            && Event.current.alt
	            && Event.current.button == 1 ) )
	        {
	            var num = 1f - Event.current.delta.y * ( ( Event.current.type != EventType.ScrollWheel ) ? -_mouse_zoom_speed : _wheel_zoom_speed );
	            var num2 = _zoom * num;
	            var num3 = Mathf.Clamp( num2, GetMinZoom(), 50f );
	            if ( num3 != _zoom )
	            {
	                _zoom = num3;
	                if ( num2 != num3 )
	                {
	                    num /= num2 / num3;
	                }
	
	                _scroll_position *= num;
	                float num4 = Event.current.mousePosition.x / _texture_view_rect.width - 0.5f;
	                float num5 = Event.current.mousePosition.y / _texture_view_rect.height - 0.5f;
	                float num6 = num4 * ( num - 1f );
	                float num7 = num5 * ( num - 1f );
	
	                var max_scroll_rect = maxScrollRect;
	                _scroll_position.x = _scroll_position.x + num6 * ( max_scroll_rect.width / 2 );
	                _scroll_position.y = _scroll_position.y + num6 * ( max_scroll_rect.height / 2 );
	
	                Event.current.Use();
	            }
	        }
	    }
	
	    protected void HandlePanning()
	    {
	        bool flag = ( !Event.current.alt && Event.current.button > 0 )
	            || ( Event.current.alt && Event.current.button <= 0 );
	        if ( flag && GUIUtility.hotControl == 0 )
	        {
	            EditorGUIUtility.AddCursorRect( _texture_view_rect, MouseCursor.Pan );
	            if ( Event.current.type == EventType.MouseDrag )
	            {
	                _scroll_position -= Event.current.delta;
	                Event.current.Use();
	            }
	        }
	        if ( ( ( Event.current.type == EventType.MouseUp || Event.current.type == EventType.MouseDown ) && flag )
	            || ( ( Event.current.type == EventType.KeyUp || Event.current.type == EventType.KeyDown )
	            && Event.current.keyCode == KeyCode.LeftAlt ) )
	        {
	            base.Repaint();
	        }
	    }
	
	    protected void DrawScreenspaceBackground()
	    {
	        if ( Event.current.type == EventType.Repaint )
	        {
	            _styles.preBackground.Draw( _texture_view_rect, false, false, false, false );
	        }
	    }
	
	    protected void HandleScrollbars()
	    {
	        Rect position = new Rect( _texture_view_rect.xMin, _texture_view_rect.yMax, _texture_view_rect.width, _scrollbar_margin );
	        _scroll_position.x = GUI.HorizontalScrollbar( position, _scroll_position.x, _texture_view_rect.width, maxScrollRect.xMin, maxScrollRect.xMax );
	        Rect position2 = new Rect( _texture_view_rect.xMax, _texture_view_rect.yMin, _scrollbar_margin, _texture_view_rect.height );
	        _scroll_position.y = GUI.VerticalScrollbar( position2, _scroll_position.y, _texture_view_rect.height, maxScrollRect.yMin, maxScrollRect.yMax );
	    }
	
	    protected void SetupHandlesMatrix()
	    {
	        Vector3 pos = new Vector3( _texture_rect.x, _texture_rect.yMax, 0f );
	        Vector3 s = new Vector3( _zoom, -_zoom, 1f );
	        Handles.matrix = Matrix4x4.TRS( pos, Quaternion.identity, s );
	    }
	
	    protected void DoTextureGUI()
	    {
	        if ( _texture != null )
	        {
	            if ( _zoom < 0f )
	            {
	                _zoom = GetMinZoom();
	            }
	
	            _texture_rect = new Rect(
	                _texture_view_rect.width / 2f - (float) _texture.width * _zoom / 2f,
	                _texture_view_rect.height / 2f - (float) _texture.height * _zoom / 2f,
	                (float) _texture.width * _zoom,
	                (float) _texture.height * _zoom );

                HandleScrollbars();
                SetupHandlesMatrix();
                HandleZoom();
                HandlePanning();
                DrawScreenspaceBackground();
                GUIClipWrapper.Push( _texture_view_rect, -_scroll_position, Vector2.zero, false );

                CalcRelativeMousePosition();

                if ( Event.current.type == EventType.Repaint )
                {
                    DrawTexturespaceBackground();
                    DrawTexture();
                    DrawGrids();

                    DrawPreviewOverlayArea();
                    DrawMarkedRegion();

                    DrawPreviewFindingPath();
                    DrawNeaestRegion();
                }

                GUIClipWrapper.Pop();
            }
	    }
	
	    protected void DrawTexturespaceBackground()
	    {
	        float num = Mathf.Max( maxRect.width, maxRect.height );
	        Vector2 b = new Vector2( maxRect.xMin, maxRect.yMin );
	        float num2 = num * 0.5f;
	        float a = ( !EditorGUIUtility.isProSkin ) ? 0.08f : 0.15f;
	        float num3 = 8f;
	
	        TileMapEditorUtility.BeginLines( new Color( 0f, 0f, 0f, a ) );
	        for ( float num4 = 0f; num4 <= num; num4 += num3 )
	        {
	            TileMapEditorUtility.DrawLine( new Vector2( -num2 + num4, num2 + num4 ) + b, new Vector2( num2 + num4, -num2 + num4 ) + b );
	        }
	        TileMapEditorUtility.EndLines();
	    }
	
	    protected void DrawTexture()
	    {
	        int num = Mathf.Min( _texture.width, 1 );
	        FilterMode filter_mode = _texture.filterMode;
	        TextureUtilWrapper.SetFilterModeNoDirty( _texture, FilterMode.Point );
	
	        if ( _show_alpha )
	        {
	            if ( _texture_alpha_override != null )
	            {
	                EditorGUI.DrawTextureTransparent( _texture_rect, _texture_alpha_override );
	            }
	            else
	            {
	                EditorGUI.DrawTextureAlpha( _texture_rect, _texture );
	            }
	        }
	        else
	        {
	            EditorGUI.DrawTextureTransparent( _texture_rect, _texture );
	        }
	
	        TextureUtilWrapper.SetFilterModeNoDirty( _texture, filter_mode );
	    }
	
	    public bool IsMouseInner( Vector2 pos )
	    {
	        if ( 0 <= pos.x && pos.x < _size.x && 0 <= pos.y && pos.y < _size.y )
	        {
	            return true;
	        }
	
	        return false;
	    }
	
	    protected virtual void DrawGrids()
	    {
	
	    }
	
	    protected virtual void CalcRelativeMousePosition()
	    {
	
	    }
	
	    protected virtual void DrawPreviewOverlayArea()
	    {
	
	    }
	
	    protected virtual void DrawMarkedRegion()
	    {
	
	    }

        protected Vector2 _preview_path_pos;
        protected int _preview_path_area_type;

        protected void ResetPrewviewPath()
        {
            _preview_path_area_type = 0x00;
            _preview_path_pos = Vector2.zero;
        }

        protected virtual void DrawPreviewFindingPath()
        {

        }

        protected virtual void DrawNeaestRegion()
        {

        }
	
	    protected virtual void RepaintWindow()
	    {
	        base.Repaint();
	    }
	
	    protected class Styles
	    {
	        public readonly GUIStyle dragdot = "U2D.dragDot";
	        public readonly GUIStyle dragdotDimmed = "U2D.dragDotDimmed";
	        public readonly GUIStyle dragdotactive = "U2D.dragDotActive";
	        public readonly GUIStyle createRect = "U2D.createRect";
	        public readonly GUIStyle preToolbar = "preToolbar";
	        public readonly GUIStyle preButton = "preButton";
	        public readonly GUIStyle preLabel = "preLabel";
	        public readonly GUIStyle preSlider = "preSlider";
	        public readonly GUIStyle preSliderThumb = "preSliderThumb";
	        public readonly GUIStyle preBackground = "preBackground";
	        public readonly GUIStyle pivotdotactive = "U2D.pivotDotActive";
	        public readonly GUIStyle pivotdot = "U2D.pivotDot";
	        public readonly GUIStyle dragBorderdot = new GUIStyle();
	        public readonly GUIStyle dragBorderDotActive = new GUIStyle();
	        public readonly GUIStyle toolbar;
	        public readonly GUIContent alphaIcon;
	        public readonly GUIContent RGBIcon;
	        public readonly GUIStyle notice;
	        public readonly GUIContent smallMip;
	        public readonly GUIContent largeMip;
	
	        public static readonly GUIContent[] spriteAlignmentOptions = new GUIContent[]
	        {
	                EditorGUIUtilityWrapper.TextContent("Center"),
	                EditorGUIUtilityWrapper.TextContent("Top Left"),
	                EditorGUIUtilityWrapper.TextContent("Top"),
	                EditorGUIUtilityWrapper.TextContent("Top Right"),
	                EditorGUIUtilityWrapper.TextContent("Left"),
	                EditorGUIUtilityWrapper.TextContent("Right"),
	                EditorGUIUtilityWrapper.TextContent("Bottom Left"),
	                EditorGUIUtilityWrapper.TextContent("Bottom"),
	                EditorGUIUtilityWrapper.TextContent("Bottom Right"),
	                EditorGUIUtilityWrapper.TextContent("Custom")
	        };
	
	        public static GUIContent s_PivotLabel = EditorGUIUtilityWrapper.TextContent( "Pivot" );
	
	        public static GUIContent s_NoSelectionWarning = EditorGUIUtilityWrapper.TextContent( "No texture or sprite selected" );
	
	        public static GUIContent s_SpriteTessellationDetail = EditorGUIUtilityWrapper.TextContent( "Tessellation Detail" );
	
	        public Styles()
	        {
	            toolbar = new GUIStyle( EditorGUIUtilityWrapper.inspectorBig );
	            toolbar.margin.top = 0;
	            toolbar.margin.bottom = 0;
	            alphaIcon = EditorGUIUtility.IconContent( "PreTextureAlpha" );
	            RGBIcon = EditorGUIUtility.IconContent( "PreTextureRGB" );
	            preToolbar.border.top = 0;
	            createRect.border = new RectOffset( 3, 3, 3, 3 );
	            notice = new GUIStyle( GUI.skin.label );
	            notice.alignment = TextAnchor.MiddleCenter;
	            notice.normal.textColor = Color.yellow;
	            dragBorderdot.fixedHeight = 5f;
	            dragBorderdot.fixedWidth = 5f;
	            dragBorderdot.normal.background = EditorGUIUtility.whiteTexture;
	            dragBorderDotActive.fixedHeight = dragBorderdot.fixedHeight;
	            dragBorderDotActive.fixedWidth = dragBorderdot.fixedWidth;
	            dragBorderDotActive.normal.background = EditorGUIUtility.whiteTexture;
	            smallMip = EditorGUIUtility.IconContent( "PreTextureMipMapLow" );
	            largeMip = EditorGUIUtility.IconContent( "PreTextureMipMapHigh" );
	        }
	    }
	}
}
